<?php
/**
 * A rail_document store binary files to the rail tree. You can store a lease one binary content.
 *
 * PHP versions 5
 *
 * Copyright (C)
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of ERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
 * Fundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *
 * @author Bastian Schröder <bs@chemanet.de>
 * @version 2007-07-19
 * @package rail
 */
class rail_document extends rail_object {

	/**
	 * Attributes which are not writeable from outside. The array contains only the name
	 * of protected attributes not the attribute itself.
	 *
	 * @var array
	 */
	protected $protected_attributes = array( OBJ_TIME_CREATE, OBJ_TIME_LASTWRITE, OBJ_DOCUMENT, DOCUMENT_MIMETYPE );


	/**
	 * Returned a copy of this rail_document.
	 *
	 * @param rail_object $pRailObject
	 * @return rail_object
	 */
	public function copy ( $pRailObject ) {
		$copy = parent::copy( $pRailObject );
		$copy->set_content( $this->get_content(), $this->get_mimetype() );

		return $copy;
	}


	/**
	 * Delete this rail_document. Remove content before deleting object.
	 *
	 * @exception rail_writepermission_exception
	 * @return bool
	 */
	public function delete () {
		// check write permission
		if( !$this->is_writeable( $this->rail_connector->get_user() ) )
			throw new rail_writepermission_exception( $this );

		// remove content
		$this->remove_content();

		return parent::delete();
	}


	/**
	 * Get documents content. The returned string can be in binary or ASCII form.
	 *
	 * @exception rail_readpermission_exception
	 * @return string
	 */
	public function get_content () {
		// check read permission
		if( !$this->is_readable( $this->rail_connector->get_user() ) )
		 	throw new rail_readpermission_exception( $this );

		if( !isset( $this->cache[ 'content' ] ) ){
			$document_id = $this->get_attribute( OBJ_DOCUMENT );
			$data = $this->rail_connector->send_request( "SELECT `content` FROM objects_documents WHERE `id`='$document_id' LIMIT 1" )->fetch_assoc();
			$this->cache[ 'content' ] = $data[ 'content' ];
		}

		return $this->cache[ 'content' ];
	}


	/**
	 * Get mime-type for this document.
	 *
	 * @exception rail_readpermission_exception
	 * @return string
	 */
	public function get_mimetype () {
		// check read permission
		if( !$this->is_readable( $this->rail_connector->get_user() ) )
		 	throw new rail_readpermission_exception( $this );

		return $this->get_attribute( DOCUMENT_MIMETYPE );
	}


	/**
	 * Return true if this rail_document has a content otherwise false.
	 *
	 * @exception rail_readpermission_exception
	 * @return bool
	 */
	public function is_content_set () {
		// check read permission
		if( !$this->is_readable( $this->rail_connector->get_user() ) )
		 	throw new rail_readpermission_exception( $this );

		return $this->get_attribute( OBJ_DOCUMENT ) > 0;
	}


	/**
	 * Remove documents content.
	 *
	 * @exception rail_writepermission_exception
	 */
	public function remove_content () {
		// check write permission
		if( !$this->is_writeable( $this->rail_connector->get_user() ) )
		 	throw new rail_writepermission_exception( $this );

		// return if no content is set
		if( !$this->is_content_set() )
			return;

		$old_document_id = $this->get_attribute( OBJ_DOCUMENT );

		// remove content attribute
		$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='' WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_DOCUMENT'" );
		$this->cache[ 'attributes' ][ OBJ_DOCUMENT ] = '';

		// check wheather the old content is shared with an other object, before deleting objects_documents
		$data = $this->rail_connector->send_request( "SELECT `object` FROM objects_attributes WHERE `value`='$old_document_id' AND `attribute`='OBJ_TIME_LASTWRITE' LIMIT 1" )->fetch_assoc();
		if( count( $data ) > 0 )
			$this->rail_connector->send_request( "DELETE FROM objects_documents WHERE `id`='$old_document_id' LIMIT 1" );

		// update OBJ_TIME_LASTWRITE attribute
		$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='" . time() . "' WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_TIME_LASTWRITE'" );
	}


	/**
	 * Set documents content. The content can be in binary or ASCII form.
	 *
	 * @exception rail_writepermission_exception
	 * @param Blob $pContent
	 * @param String $pMimeType
	 */
	public function set_content ( $pContent, $pMimeType = '' ) {
		// check write permission
		if( !$this->is_writeable( $this->rail_connector->get_user() ) )
		 	throw new rail_writepermission_exception( $this );

		$md5 = md5($pContent);
		$old_document_id = $this->get_attribute( OBJ_DOCUMENT );

		// check wheater md5 checksum exist in objects_documents
		$data = $this->rail_connector->send_request( "SELECT `id` FROM objects_documents WHERE `md5`='$md5' LIMIT 1" )->fetch_assoc();
		// exist, so update attribute
		if( count( $data ) > 0 ){
			$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='" . $data['id'] . "' WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_DOCUMENT'" );
			$document_id = $data['id'];
		}
		// not found. create new objects_documents
		else{
			$this->rail_connector->send_request( "INSERT INTO objects_documents (`md5`,`content`) VALUES ('$md5', '" . addslashes( $pContent ) . "')" );
			$data = $this->rail_connector->send_request( "SELECT `id` FROM objects_documents WHERE `md5`='$md5' ORDER BY id DESC LIMIT 1" )->fetch_assoc();
			$document_id = $data['id'];
		}

		// update attribute
		$data = $this->rail_connector->send_request( "SELECT `value` FROM objects_attributes WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_DOCUMENT' LIMIT 1" )->fetch_assoc();
		if( count($data) > 0 )
			$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='$document_id' WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_DOCUMENT'" );
		else
			$this->rail_connector->send_request( "INSERT INTO objects_attributes (`object`,`attribute`,`value`) VALUES ('" . $this->get_id() . "','OBJ_DOCUMENT','$document_id')" );
		$this->cache[ 'attributes' ][ OBJ_DOCUMENT ] = $document_id;

		// update mimetype if requested
		if( strlen( $pMimeType ) > 0 )
			$this->set_mimetype( $pMimeType );

		// check wheather the old content is shared with an other object, before deleting objects_documents
		$data = $this->rail_connector->send_request( "SELECT `object` FROM objects_attributes WHERE `value`='$old_document_id' AND `attribute`='OBJ_TIME_LASTWRITE' LIMIT 1" )->fetch_assoc();
		if( count( $data ) > 0 )
			$this->rail_connector->send_request( "DELETE FROM objects_documents WHERE `id`='$old_document_id' LIMIT 1" );

		// update OBJ_TIME_LASTWRITE attribute
		$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='" . time() . "' WHERE `object`='" . $this->get_id() . "' AND `attribute`='OBJ_TIME_LASTWRITE'" );
	}


	/**
	 * Set documents mime-type. You can use the global rail_mimetypes array to find a valid mime-type.
	 *
	 * @exception rail_readpermission_exception
	 * @param String $pMimeType
	 * @return string
	 */
	public function set_mimetype ( $pMimeType = '' ) {
		// check write permission
		if( !$this->is_writeable( $this->rail_connector->get_user() ) )
		 	throw new rail_writepermission_exception( $this );

		// write to databases
		$data = $this->rail_connector->send_request( "SELECT `value` FROM objects_attributes WHERE `object`='" . $this->get_id() . "' AND `attribute`='DOCUMENT_MIMETYPE' LIMIT 1" )->fetch_assoc();
		if( count($data) > 0 )
			$this->rail_connector->send_request( "UPDATE objects_attributes SET `value`='$pMimeType' WHERE `object`='" . $this->get_id() . "' AND `attribute`='DOCUMENT_MIMETYPE'" );
		else
			$this->rail_connector->send_request( "INSERT INTO objects_attributes (`object`,`attribute`,`value`) VALUES ('" . $this->get_id() . "','DOCUMENT_MIMETYPE','$pMimeType')" );
		// update attribute cache
		$this->cache[ 'attributes' ][ DOCUMENT_MIMETYPE ] = $pMimeType;
	}

} // End of rail_document
?>